/* See LICENSE for copyright and terms of use */

import org.evtmng.events.TweenEventInfo;
import org.evtmng.tween.Tween;
import org.evtmng.util.List;
import org.evtmng.util.Set;

/**
 * <p>Listeners are placed in {@link org.evtmng.util.Set}s organized by tweens into
 * {@link org.evtmng.util.List}s.</p>
 *
 * <p>
 * Internal representation:<br/>
 * &lt;{@link org.evtmng.util.List}&gt;<br/>
 * |-{@link org.evtmng.tween.Tween#id()}<br/>
 * &nbsp;|-{@link org.evtmng.util.Set}<br/>
 * &nbsp;&nbsp;|-0: listener1<br/>
 * &nbsp;&nbsp;|-1: listener2<br/>
 * &nbsp;&nbsp;...<br/>
 * &nbsp;...<br/>
 * ...
 * </p>
 *
 * <p>Very similar to {@link org.as2lib.env.event.broadcaster.EventBroadcaster}.</p>
 *
 * @see org.evtmng.tween.Tween#id()
 * @author Tay Ray Chuan
 */

class org.evtmng.events.TweenListenerBroadcaster {
	private static var g_instance:TweenListenerBroadcaster;

	public static function instance():TweenListenerBroadcaster {
		if (g_instance == null) {
			g_instance = new TweenListenerBroadcaster();
		}
		return g_instance;
	}

	/**
	 * <p>Maps an event onto a corresponding method name.</p>
	 *
	 * @see org.evtmng.events.IStartListener
	 * @see org.evtmng.events.IRunListener
	 * @see org.evtmng.events.IEndListener
	 */
	public static var EVENTS:Object = {
	start: "onTweenStart",
	run: "whileRunningTween",
	end: "onTweenEnd"
	};

	/**
	 * @return Name of method in {@link org.evtmng.events.IStartListener}.
	 */
	public static function get START_LSER_NAME():String {
		return EVENTS.start;
	}

	/**
	 * @return Name of method in {@link org.evtmng.events.IRunListener}.
	 */
	public static function get RUN_LSER_NAME():String {
		return EVENTS.run;
	}

	/**
	 * @return Name of method in {@link org.evtmng.events.IEndListener}.
	 */
	public static function get END_LSER_NAME():String {
		return EVENTS.end;
	}

	private var m_listeners_for_tween:List;

	private function TweenListenerBroadcaster() {
		m_listeners_for_tween = new List();
	}

	public function addListenerForTween(listener:Object, tween:Tween):Void {
		listenersForTweenId(tween.id()).addItem(listener);
	}

	public function removeListenerForTween(listener:Object, tween:Tween):Void {
		Set(m_listeners_for_tween.itemForId(tween.id())).removeItem(listener);
	}

	public function dispatch(info:TweenEventInfo):Void {
		var list:Array = listenersForTweenId(info.tween().id()).internalList();
		for(var i:String in list) {
			list[i][info.getName()](info);
		}
	}

	public function listenersForTweenId(id:Number):Set {
		if(m_listeners_for_tween.itemForId(id)==null) {
			m_listeners_for_tween.addItemWithId(new Set(), id);
		}
		return Set(m_listeners_for_tween.itemForId(id));
	}
}